﻿#region Copyright (c) 2010 R. Uittenbosch
/*
* Copyright (C) 2010 R. Uittenbosch
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
* associated documentation files (the "Software"), to deal in the Software without restriction, including 
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 
* following conditions:
* 
* The above copyright notice and this permission notice shall be included in all copies or substantial 
* portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 
* EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#endregion

using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Mobile.Mvc;
using TouchUI.System.Mobile.Mvc;
using LinkedIn.Mobile.Properties;

namespace LinkedIn.Mobile
{

  /// <summary>
  /// The mainForm is the principal visible form of the application.
  /// In displays the bottom actionmenu and propagates all paint en click events to
  /// the different TouchUI Dialogs. 
  /// The Hide method has been override in order to prevent the form to become unvisible
  /// due to the appearence fo ofher 'ViewForm's like the Security and Status forms
  /// </summary>
  public partial class MainForm : ViewForm, IView
  {
    #region ControllerEvents

    [PublishEvent("OnPropagateEvent")]
    public event PropagateEventHandler OnPropagateEvent;
    #endregion

    #region Private variables
    private Timer timer;
    private int animationLeft;
    private int animationOffset;
    private bool loaded = false;
    #endregion

    #region Constructor
    
    public MainForm()
    {
      InitializeComponent();

      actionMenu.Commands = new string[] { "Status", "Connections", "Profile", "Updates" };
      actionMenu.Execute += new EventHandler<ExecuteCommandEventArgs>(bottomMenu_Execute);
     
      this.MenuMenu.Text        = Strings.Menu;
      this.exitBtn.Text         = Strings.Exit;
      this.ProfileMenu.Text     = Strings.MyProfile;
      this.ConnectionsMenu.Text = Strings.MyConnections;
      this.StatusMenu.Text      = Strings.MyStatus;
      this.UpdatesMenu.Text     = Strings.Updates;
      this.SearchMenu.Text      = Strings.Search;
      this.InviteMenu.Text      = Strings.InviteMenu;
      this.Text                 = Strings.ProgramName;
      this.AuthenticateMenu.Text= Strings.Authenticate;
    }

    #endregion

    #region ActionMenu
    /// <summary>
    /// The user clicked on the action menu
    /// Send an action to the mainform controller
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void bottomMenu_Execute(object sender, ExecuteCommandEventArgs e)
    {
      SendAction(e.CommandText);
    }


    /// <summary>
    /// Send the action from the menu to the controller. Use the waitcursor
    /// to show we are busy
    /// </summary>
    /// <param name="action"></param>
    private void SendAction(string action)
    {
      Invalidate();
     // Application.DoEvents();
      this.ViewData["Action"] = action;
      Cursor.Current = Cursors.WaitCursor;
      this.OnViewStateChanged("Action");
      Cursor.Current = Cursors.Default;
    }
    #endregion

    #region Notification of the controller
    /// <summary>
    /// The view has to be updated
    /// </summary>
    /// <param name="key"></param>
    protected override void OnUpdateView(string key)
    {
      if (key == "Status")
      {
        MessageBox.Show((string)ViewData["Status"]);
      }
      if (key == "Authentication")
      {
        // nothing
      }
      if (key == "Permission")
      {
        permissionOk = true;
        authenticated = false;
      }
      // Reset the waitcursor
      Cursor.Current = Cursors.Default;
    }
    #endregion

    #region Activated/Deactivate
    /// <summary>
    /// Authentication needs to wait a little....
    /// so use a timer
    /// </summary>
    bool authenticated = false;
    bool permissionOk = false;
    private void timer_Tick(object sender, EventArgs e)
    {
      this.Refresh();
      // Check permission
      if (!permissionOk) SendAction("Permission");
      else if (!authenticated)
      {
        // Only send the event once.
        authenticated = true;
        SendAction("Authenticate");
      }
      
    }

    private void MainForm_Load(object sender, EventArgs e)
    {
      // Set the refresh timer
      timer = new Timer()
      {
        Interval = 40 // 12.5 fps
      };

      timer.Tick += new EventHandler(timer_Tick);
      timer.Enabled = true;

      loaded = true;

    }


    /// <summary>
    /// Disable the timer if we aren't the topmost form
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MainForm_Activated(object sender, EventArgs e)
    {
      if (loaded)
        timer.Enabled = true;


    }

    /// <summary>
    /// Enable the timer if we are back on top
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MainForm_Deactivate(object sender, EventArgs e)
    {
      if (loaded)
        timer.Enabled = false;
    }
    #endregion

    #region ActionPropagate
    /// <summary>
    /// Propagate all event
    /// </summary>
    /// <param name="e"></param>
    private void Propagate(PropagateEventArgs e)
    {
      if (OnPropagateEvent != null)
      {
        OnPropagateEvent(this, e);
      }
    }

    private void MainForm_MouseDown(object sender, MouseEventArgs e)
    {
      // Where is the mouse?
      if (actionMenu.Bounds.Inside(new Point(e.X, e.Y)))
        actionMenu.MouseDown(new Point(e.X, e.Y));
      else
        Propagate(new PropagateEventArgs(PropagateAction.MouseDown, e));
    }

    private void MainForm_MouseMove(object sender, MouseEventArgs e)
    {
      // Where is the mouse?
      if (actionMenu.Bounds.Inside(new Point(e.X, e.Y)))
        actionMenu.MouseMove(new Point(e.X, e.Y));
      else
        Propagate(new PropagateEventArgs(PropagateAction.MouseMove, e));
    }

    private void MainForm_MouseUp(object sender, MouseEventArgs e)
    {
      // Where is the mouse?
      if (actionMenu.Bounds.Inside(new Point(e.X, e.Y)))
        actionMenu.MouseUp(new Point(e.X, e.Y));
      else
        Propagate(new PropagateEventArgs(PropagateAction.MouseUp, e));
    }

   
    private void MainForm_KeyUp(object sender, KeyEventArgs e)
    {
      if (!Zooming(e))
        Propagate(new PropagateEventArgs(PropagateAction.KeyUp, e));     
    }
    private void MainForm_KeyDown(object sender, KeyEventArgs e)
    {
      UpdateZoom(e);
      Propagate(new PropagateEventArgs(PropagateAction.KeyDown, e));
    }

    private bool downKeyPressed = false;
    private bool upKeyPressed   = false;

    private PropagateAction zoomAction = PropagateAction.NoZoom;

    private bool Zooming(KeyEventArgs key)
    {
      bool zoomCaptured = false;
      // Currently zooming?
      if (zoomAction == PropagateAction.Zooming)
      {
        if (key.KeyCode == Keys.Down)
          zoomAction = PropagateAction.ZoomDown;
        else if (key.KeyCode == Keys.Up)
          zoomAction = PropagateAction.ZoomUp;
        else
          zoomAction = PropagateAction.NoZoom;

        if (key.KeyCode == Keys.F20)
        {
          if (zoomAction == PropagateAction.ZoomUp || zoomAction == PropagateAction.ZoomDown)
          {
            Common.Instance.ZoomFactor += (zoomAction == PropagateAction.ZoomUp)?-1:1;
            Common.Instance.UpdateZoom();
            Propagate(new PropagateEventArgs(zoomAction,key));
            zoomCaptured = true;
          }
          zoomAction = PropagateAction.NoZoom;
        }        
      }
      return zoomCaptured;
    }
    private void UpdateZoom(KeyEventArgs key)
    {
      // F20 -> zooming
      if (key.KeyCode == Keys.F20)
        zoomAction = (downKeyPressed || upKeyPressed) ? PropagateAction.Zooming : PropagateAction.NoZoom ;

      downKeyPressed = (key.KeyCode == Keys.Down);
      upKeyPressed   = (key.KeyCode == Keys.Up);


    }

    #endregion



    #region Resize and Paint
    private void MainForm_Resize(object sender, EventArgs e)
    {
      Common.Instance.ClientRectangle = Screen.PrimaryScreen.WorkingArea;
      Common.Instance.ClientRectangle = new Rectangle(
                    Screen.PrimaryScreen.WorkingArea.X, 
                    Screen.PrimaryScreen.WorkingArea.Y, 
                    Screen.PrimaryScreen.WorkingArea.Width, this.Height);
                    //Screen.PrimaryScreen.WorkingArea.Height - Common.Instance.AdjustBottomHeigth);

      if (loaded)
        Propagate(new PropagateEventArgs(PropagateAction.Resize));


      this.Refresh();
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
     // No background painting, we do custom painting 
    }

    public new void Hide()
    {
      // Nothing
    }

    private void SetMenuItems()
    {

      // AuthenticationPending, and no current user -> enable
      if (ApplicationManager.Configuration.GetItem("AuthenticationPending", false) &&
        (string.IsNullOrEmpty(ApplicationManager.Configuration.GetItem<string>("CurrentUser"))))
      {
        // Disabele the rest.
        foreach (MenuItem i in MenuMenu.MenuItems)
          i.Enabled = false;

        if (!MenuMenu.MenuItems.Contains(AuthenticateMenu))
          MenuMenu.MenuItems.Add(AuthenticateMenu);

        AuthenticateMenu.Enabled = true;
      }
      else
      {
        // Other way around
        foreach (MenuItem i in MenuMenu.MenuItems)
          i.Enabled = true;

        // Remove the menu all together.
        MenuMenu.MenuItems.Remove(AuthenticateMenu);
        AuthenticateMenu.Enabled = false;
      }

      // By default disabled.
      InviteMenu.Enabled = false;
      // If we can invite the person, show the InviteMenu.
      if (ApplicationManager.LastPerson != null)
        if (ApplicationManager.LastPerson.Distance != 1)
          if (ApplicationManager.LastPerson.Id != ApplicationManager.Configuration.GetItem<string>("CurrentUser"))
            InviteMenu.Enabled = true;

    }

    protected override void OnPaint(PaintEventArgs e)
    {
      // Draw the actionmenu
      //actionMenu.Paint(e.Graphics);

      if (!loaded)
        return;

      SetMenuItems();
       Rectangle r = Common.Instance.ClientRectangle;

      // Paint the topmost panel inside the paintcopybitmap
      Propagate(new PropagateEventArgs(PropagateAction.Paint));
     
      // Use animation to show the control
      if (animationLeft != 0)
      {
        e.Graphics.DrawImage(Common.Instance.PaintCopyBitmap,
            new Rectangle(animationLeft - r.Width * animationLeft.CompareTo(0), 0, r.Width, r.Height),
            r, GraphicsUnit.Pixel);
        e.Graphics.DrawImage(Common.Instance.PaintBitmap, new Rectangle(animationLeft, 0, r.Width, r.Height), r, GraphicsUnit.Pixel);
        animationLeft -= animationOffset;
        if (Math.Abs(animationLeft) < Math.Abs(animationOffset))
          animationLeft = 0;
      }
      else
        e.Graphics.DrawImage(Common.Instance.PaintBitmap, r, r, GraphicsUnit.Pixel);
    }
    #endregion

    #region Menu
    private void exitBtn_Click(object sender, EventArgs e)
    {
      Application.Exit();
    }


    private void UpdatesMenu_Click(object sender, EventArgs e)
    {
      SendAction("Updates");
    }


    private void ConnectionsMenu_Click(object sender, EventArgs e)
    {
      SendAction("Connections");
    }

    private void StatusMenu_Click(object sender, EventArgs e)
    {
      SendAction("Status");
    }

    private void ProfileMenu_Click(object sender, EventArgs e)
    {
      SendAction("Profile");
    }

    private void SearchMenu_Click(object sender, EventArgs e)
    {
        SendAction("Search");
    }
    #endregion

    private void InviteMenu_Click(object sender, EventArgs e)
    {
      SendAction("Invite");
    }

    private void AuthenticateMenu_Click(object sender, EventArgs e)
    {
      SendAction("ReAuthenticate");
    }   

  }
  
}